﻿using System;
using System.Security.Cryptography;

/// <summary>
/// 防止修改的数据,每一次复制，都会重新生成两个值
/// 避免修改
/// </summary>
[Serializable]
public class SmartValue
{
    private float _cachedSum = 0; // 缓存 m_fValue1 + m_fValue2 的结果
    public int m_nSeed = 0;
    public float m_fValue1;
    public float m_fValue2;

    public SmartValue()
    {
        SetValue(0);
    }

    public SmartValue(float fData)
    {
        SetValue(fData);
    }

    public SmartValue(int fData)
    {
        SetValue(fData);
    }

    public long GetLong()
    {
        return (long)GetFloat();
    }

    public int GetInt()
    {
        return (int)GetFloat();
    }

    public float GetFloat()
    {
        if (_cachedSum == 0)
        {
            _cachedSum = m_fValue1 + m_fValue2;
        }
        return _cachedSum;
    }

    public void SetValue(float fData)
    {
        if (float.IsNaN(fData) || float.IsInfinity(fData))
        {
            throw new ArgumentException("Input value is invalid.");
        }

        m_nSeed = GenerateRandomInt(0, 100000);
        m_fValue1 = GenerateRandomFloat(-m_nSeed, m_nSeed);
        m_fValue2 = fData - m_fValue1;
        _cachedSum = 0; // 清空缓存
    }

    public void SetValue(int nData)
    {
        if (nData < int.MinValue || nData > int.MaxValue)
        {
            throw new ArgumentException("Input value is out of range.");
        }

        m_nSeed = GenerateRandomInt(0, 100000);
        m_fValue1 = GenerateRandomInt(-1000, 1000);
        m_fValue2 = nData - m_fValue1;
        _cachedSum = 0; // 清空缓存
    }

    private static int GenerateRandomInt(int min, int max)
    {
        byte[] buffer = new byte[sizeof(int)];
        using (var rng = RandomNumberGenerator.Create())
        {
            rng.GetBytes(buffer);
        }
        int result = BitConverter.ToInt32(buffer, 0);
        return Math.Abs(result % (max - min + 1)) + min;
    }

    private static float GenerateRandomFloat(float min, float max)
    {
        byte[] buffer = new byte[sizeof(int)];
        using (var rng = RandomNumberGenerator.Create())
        {
            rng.GetBytes(buffer);
        }
        int result = BitConverter.ToInt32(buffer, 0);
        return (result % 1000000) / 1000000f * (max - min) + min;
    }

    #region Operator Overloads

    private static SmartValue PerformOperation(SmartValue a, SmartValue b, Func<float, float, float> operation)
    {
        SmartValue sv = new SmartValue();
        sv.SetValue(operation(a.GetFloat(), b.GetFloat()));
        return sv;
    }

    private static SmartValue PerformOperation(float a, SmartValue b, Func<float, float, float> operation)
    {
        SmartValue sv = new SmartValue();
        sv.SetValue(operation(a, b.GetFloat()));
        return sv;
    }

    private static SmartValue PerformOperation(SmartValue a, float b, Func<float, float, float> operation)
    {
        SmartValue sv = new SmartValue();
        sv.SetValue(operation(a.GetFloat(), b));
        return sv;
    }

    public static SmartValue operator *(SmartValue a, SmartValue b) => PerformOperation(a, b, (x, y) => x * y);
    public static SmartValue operator /(SmartValue a, SmartValue b)
    {
        if (b.GetFloat() == 0)
        {
            throw new DivideByZeroException("Division by zero is not allowed.");
        }
        return PerformOperation(a, b, (x, y) => x / y);
    }
    public static SmartValue operator -(SmartValue a, SmartValue b) => PerformOperation(a, b, (x, y) => x - y);
    public static SmartValue operator +(SmartValue a, SmartValue b) => PerformOperation(a, b, (x, y) => x + y);

    public static SmartValue operator *(float a, SmartValue b) => PerformOperation(a, b, (x, y) => x * y);
    public static SmartValue operator /(float a, SmartValue b)
    {
        if (b.GetFloat() == 0)
        {
            throw new DivideByZeroException("Division by zero is not allowed.");
        }
        return PerformOperation(a, b, (x, y) => x / y);
    }
    public static SmartValue operator -(float a, SmartValue b) => PerformOperation(a, b, (x, y) => x - y);
    public static SmartValue operator +(float a, SmartValue b) => PerformOperation(a, b, (x, y) => x + y);

    public static SmartValue operator *(SmartValue a, float b) => PerformOperation(a, b, (x, y) => x * y);
    public static SmartValue operator /(SmartValue a, float b)
    {
        if (b == 0)
        {
            throw new DivideByZeroException("Division by zero is not allowed.");
        }
        return PerformOperation(a, b, (x, y) => x / y);
    }
    public static SmartValue operator -(SmartValue a, float b) => PerformOperation(a, b, (x, y) => x - y);
    public static SmartValue operator +(SmartValue a, float b) => PerformOperation(a, b, (x, y) => x + y);

    #endregion
}